package com.m1.tzolkin.model.board;

import java.util.ArrayList;
import java.util.Collection;

import com.m1.tzolkin.model.TzolkinConstants;
import com.m1.tzolkin.model.buildables.IActionBuilding;
import com.m1.tzolkin.model.buildables.IFarm;
import com.m1.tzolkin.model.buildables.IMonument;
import com.m1.tzolkin.model.buildables.IZonedBuilding;
import com.m1.tzolkin.model.exceptions.CannotBuildException;
import com.m1.tzolkin.model.exceptions.EndOfGameException;
import com.m1.tzolkin.model.exceptions.NoAvailableSkullException;
import com.m1.tzolkin.model.exceptions.NotEnoughCornException;
import com.m1.tzolkin.model.exceptions.NotEnoughResourceException;
import com.m1.tzolkin.model.exceptions.WaitingOperationsException;
import com.m1.tzolkin.model.players.ITZPlayer;

public class BuildBoard extends TempleBoard implements IBuildBoard, TzolkinConstants {
	
	// ATTRIBUTS
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -273175881760964061L;
	protected final Collection<IZonedBuilding> buildings;
	protected final Collection<IMonument> monuments;
	// Construction de b�timents
	private int buildBuildings;
	// Construction de monuments
	private int buildMonuments;
		
	// CONSTRUCTEUR
	
	public BuildBoard(Collection<ITZPlayer> players) {
		super(players);
		// Initialisation des b�timents
		buildings = new ArrayList<IZonedBuilding>();
		// Initialisation des monuments
		monuments = new ArrayList<IMonument>();
		IMonument m;
		for (int i = 0; i < BUILDINGS_NB - (MAX_PLAYERS - getPlayers().size()); ++i) {
			m = getBank().getMonument();
			if (m == null) break;
			monuments.add(m);
		}
		completeBuildings();
	}
	
	// REQUETES

	@Override
	public Collection<IZonedBuilding> getBuildings() {
		return new ArrayList<IZonedBuilding>(buildings);
	}
	
	@Override
	public Collection<IMonument> getMonuments() {
		return new ArrayList<IMonument>(monuments);
	}

	@Override
	public int canBuildBuildings() {
		return buildBuildings;
	}

	@Override
	public int canBuildMonuments() {
		return buildMonuments;
	}
	
	// COMMANDES
	
	@Override
	public void build(IFarm b) throws NotEnoughCornException, NotEnoughResourceException, NoAvailableSkullException, CannotBuildException {
		if (b == null || !getBuildings().contains(b)) {
			throw new IllegalArgumentException();
		}
		getCurrentPlayer().addFarm(b);
		getLog().addSentence(new String[] {
			getCurrentPlayer().getName(), "BUILDS", "1", "FARM"
		});
		buildings.remove(b);
		listeners.firePropertyChange("buildings", null, null);
	}
	
	@Override
	public void build(IActionBuilding b) throws NotEnoughCornException, NotEnoughResourceException, NoAvailableSkullException, CannotBuildException {
		if (b == null || !getBuildings().contains(b)) {
			throw new IllegalArgumentException();
		}
		getCurrentPlayer().addBuilding(b);
		getLog().addSentence(new String[] {
			getCurrentPlayer().getName(), "BUILDS", "1", "BUILDING"
		});
		buildings.remove(b);
		listeners.firePropertyChange("buildings", null, null);
	}
	
	@Override
	public void build(IMonument b) throws NotEnoughCornException, NotEnoughResourceException, NoAvailableSkullException, CannotBuildException {
		if (b == null || !getMonuments().contains(b)) {
			throw new IllegalArgumentException();
		}
		getCurrentPlayer().addMonument(b);
		getLog().addSentence(new String[] {
			getCurrentPlayer().getName(), "BUILDS", "1", "MONUMENT"
		});
		monuments.remove(b);
		listeners.firePropertyChange("monuments", null, null);
	}
	
	@Override
	public void incTurn(int d) throws EndOfGameException, WaitingOperationsException {
		completeBuildings();
		super.incTurn(d);
	}

	@Override
	public void setBuildBuildings(int i) {
		if (i < 0) {
			throw new IllegalArgumentException();
		}
		buildBuildings = i;
		listeners.firePropertyChange("canBuild", 0, i);
	}

	@Override
	public void setBuildMonuments(int i) {
		if (i < 0) {
			throw new IllegalArgumentException();
		}
		buildMonuments = i;
		listeners.firePropertyChange("canMonument", null, null);
	}
	
	// OUTILS
	
	private void completeBuildings() {
		IZonedBuilding b;
		int old = buildings.size();
		for (int i = buildings.size(); i < BUILDINGS_NB; ++i) {
			b = getBank().getBuilding();
			if (b == null) break;
			buildings.add(b);
		}
		listeners.firePropertyChange("buildings", old, buildings.size());
	}
	
}
